1 /**
2  * License:
3  *              Copyright Devisualization (Richard Andrew Cattermole) 2014 - 2017.
4  *     Distributed under the Boost Software License, Version 1.0.
5  *        (See accompanying file LICENSE_1_0.txt or copy at
6  *              http://www.boost.org/LICENSE_1_0.txt)
7  */
8 module devisualization.util.core.assetmanager;
9 
10 /**
11  * Loads assest based upon, local to program, defaults, application provided, system locatiom and user location.
12  * Supports bin2d's generated modules to load from.
13  */
14 deprecated("An asset manager should be based upon a VFS.")
15 struct AssetManager(T) {
16     private __gshared {
17         T[string] local;
18         T[string] defaults;
19         T[string] apps;
20         T[string] systems;
21         T[string] users;
22         
23         string localPath, userPath, systemPath;
24     }
25 	
26 	this(string dirIndex, string app, string company = null, string customSystemInstallDirectory=null) {
27         import std.path : buildPath, baseName;
28         import std.process : environment;
29         localPath = buildPath(dirIndex);
30         
31         version(Windows) {
32             if (company is null) {
33                 userPath = buildPath(environment["LOCALAPPDATA"], app, dirIndex);
34                 
35                 if (customSystemInstallDirectory is null)
36 					systemPath = buildPath(environment["PROGRAMFILES"], app, dirIndex);
37                 else
38 					systemPath = buildPath(customSystemInstallDirectory, app, dirIndex);
39             } else {
40                 userPath = buildPath(environment["LOCALAPPDATA"], company, app, dirIndex);
41                 if (customSystemInstallDirectory is null)
42 					systemPath = buildPath(environment["PROGRAMFILES"], company, app, dirIndex);
43                 else
44 					systemPath = buildPath(customSystemInstallDirectory, company, app, dirIndex);
45             }
46         } else version(Posix) {
47             if (company is null) {
48                 userPath = buildPath(environment["HOME"], app, dirIndex);
49                 
50                 if (customSystemInstallDirectory is null)
51                     programFilesPath = buildPath("/usr/share", app, dirIndex);
52                 else
53                     programFilesPath = buildPath(customSystemInstallDirectory, app, dirIndex);
54             } else {
55                 userPath = buildPath(environment["HOME"], company, app, dirIndex);
56                 
57                 if (customSystemInstallDirectory is null)
58                     programFilesPath = buildPath("/usr/share", company, app, dirIndex);
59                 else
60                     programFilesPath = buildPath(customSystemInstallDirectory, company, app, dirIndex);
61             }
62         } else {
63             static assert(0, "Have not implemented storage locations for platform.");
64         }
65         
66         update();
67     }
68     
69     /**
70      * Registers a default assest value provided by the application
71      *
72      * Params:
73      *     mod    =    Name of assest
74      *     value  =    The value of the asset
75      */
76     void registerDefault(string mod, T value) { defaults[mod] = value; }
77     
78     /**
79      * Registers an assest value provided by the application
80      *
81      * Params:
82      *     mod    =    Name of asset
83      *     value  =    The value of the asset
84      */
85     void registerApp(string mod, T value) { apps[mod] = value; }
86     
87     /**
88      * Registers application assets that was compiled in via Bin2d
89      *
90      * Params:
91      *     filterExtension  =    Extension of files to only use
92      *     asDefault        =    Is this a default value or application override? Default: true (default value)
93      */
94     void registerFromBin2d(string bin2dmod)(string filterExtension, bool asDefault=true) {
95         import std.algorithm : canFind;
96         import std..string : tr;
97         import std.path : extension;
98         mixin("import " ~ bin2dmod ~ ";");
99         
100         foreach(i, fn; assetNames) {
101 			string oname = assetOriginalNames[i];
102             if (oname.extension == filterExtension) {
103                 if (asDefault)
104                     registerDefault(oname, cast(T)assetValues[i]);
105                 else
106                     registerApp(oname, cast(T)assetValues[i]);
107             }
108         }
109     }
110 
111     /**
112      * Gets an assest based upon its name
113      *
114      * Params:
115      *     mod    =    Name of asset
116      */
117     T opIndex(string mod) {
118         if (mod in local) return local[mod];
119         if (mod in apps) return apps[mod];
120         if (mod in users) return users[mod];
121         if (mod in systems) return systems[mod];
122         return defaults.get(mod, T.init);
123     }
124     
125     /**
126      * Updates all files from the file system.
127      * Looks in local to application, user application directories and system application directories
128      */
129     void update() {
130         local = getFilesFromFileSystem(localPath);
131         users = getFilesFromFileSystem(userPath);
132         systems = getFilesFromFileSystem(systemPath);
133     }
134     
135     private {
136         import std.file : exists, mkdirRecurse, isDir, dirEntries, SpanMode, read, FileException;
137 		import std.path : baseName;
138         
139         T[string] getFilesFromFileSystem(string dir)
140         in {
141             try {
142                 if (exists(dir)) {
143                     if (isDir(dir)) {
144                         // directory exists.
145                     } else {
146                         // I don't know how to handle this *shrugs*
147                     }
148                 } else {
149                     mkdirRecurse(dir);
150                 }
151             } catch (Error e) {
152             } catch (Exception e) {
153             }
154         } body {
155             T[string] ret;
156             if (exists(dir) && isDir(dir)) {
157                 // once we get here we already _know_ the directory exists
158                 foreach(string entry; dirEntries(dir, SpanMode.shallow)) {
159                     ret[baseName(entry)] = cast(T)read(entry);
160                 }
161             }
162             return ret;
163         }
164     }
165 }